package com.lauor.smpedr.spring;

import com.lauor.smpedr.session.SqlSessionFactory;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

/**
 * spring事务回调
 */
public class SqlSessionTransactionSyncAdapter extends TransactionSynchronizationAdapter {
    private SqlSessionFactory sqlSessionFactory;

    private SqlSessionHolder sqlSessionHolder;

    private boolean sqlSessionHolderActive = true;

    public SqlSessionTransactionSyncAdapter(SqlSessionFactory sqlSessionFactory, SqlSessionHolder sqlSessionHolder) {
        Assert.notNull(sqlSessionFactory, "{sqlSessionFactory} must be not null");
        Assert.notNull(sqlSessionHolder, "{sqlSessionHolder} must be not null");

        this.sqlSessionFactory = sqlSessionFactory;
        this.sqlSessionHolder = sqlSessionHolder;
    }

    @Override
    public int getOrder() {
        return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 1;
    }

    @Override//事务终止回调
    public void suspend() {
        if (this.sqlSessionHolderActive){
            TransactionSynchronizationManager.unbindResource(this.sqlSessionFactory);
        }
    }

    @Override
    public void resume() {//重试
        if (this.sqlSessionHolderActive){
            TransactionSynchronizationManager.bindResource(this.sqlSessionFactory, this.sqlSessionHolder);
        }
    }

    @Override
    public void beforeCommit(boolean readOnly) {
        if ( TransactionSynchronizationManager.isActualTransactionActive() ){
            this.sqlSessionHolder.getSqlSession().commit();
        }
    }

    @Override
    public void beforeCompletion() {
        if ( !this.sqlSessionHolder.isOpen() ) return;
        //从threadLocal移除
        TransactionSynchronizationManager.unbindResource(this.sqlSessionFactory);
        //释放数据库连接
        this.sqlSessionHolder.getSqlSession().close();
    }

    @Override
    public void afterCompletion(int status) {
        if (this.sqlSessionHolderActive) {
            TransactionSynchronizationManager.unbindResourceIfPossible(this.sqlSessionFactory);
            this.sqlSessionHolderActive = false;
            this.sqlSessionHolder.getSqlSession().close();
        }
        this.sqlSessionHolder.reset();
    }
}
